package cache

import (
	"errors"
	"time"

	"gitee.com/gousing/cache/storage"
	"gitee.com/gousing/values"
)

var errValueIsNotSlice = errors.New("cache: value Type is NOT a slice Type")

// GetSliceAny 获取 []any 类型的缓存值, 如果不存在或已经过期则返回空值
func GetSliceAny(key string) []any {
	val, _ := GetSliceAnyE(key)
	return val
}

// GetSliceAnyD  获取 []any 类型的缓存值, 如果不存在或已经过期则返回defaultVal指定的默认值
func GetSliceAnyD(key string, defaultVal []any) []any {
	if key == "" {
		return defaultVal
	}
	if to, err := GetSliceAnyE(key); err == nil {
		return to
	}
	return defaultVal
}

// GetSliceAnyD  获取 []any 类型的缓存值, 如果不存在或已经过期则返回 []any 空值切片和错误信息
func GetSliceAnyE(key string) ([]any, error) {
	toVal := []any{}
	if key == "" {
		return toVal, storage.ErrKeyIsEmpty
	}
	err := GetDefault().Scan(key, &toVal)
	if err == nil {
		return toVal, nil
	}
	return toVal[:0], err
}

// GetSliceAs 获取 []T 类型的缓存值, 如果不存在或已经过期则返回空值
//   - 支持转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceAs[T values.TypeBase | values.TypeBaseSlice](key string) []T {
	val, _ := GetSliceAsE[T](key)
	return val
}

// GetSliceAsD 获取 []T 类型的缓存值, 如果不存在或已经过期则返回默认值
//   - 支持转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceAsD[T values.TypeBase | values.TypeBaseSlice](key string, defaultVal []T) []T {
	if key == "" {
		return defaultVal
	}
	val, err := GetSliceAsE[T](key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetSliceAsE 获取 []T 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 支持转换目标为任意类型的 []TypeBase 和 [][]TypeBase 切片, 如果转换失败, 则返回空的 []T 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceAsE[T values.TypeBase | values.TypeBaseSlice](key string) ([]T, error) {
	toVal := []T{}
	if key == "" {
		return toVal, storage.ErrKeyIsEmpty
	}
	err := GetDefault().Scan(key, &toVal)
	if err == nil {
		return toVal, nil
	}
	toVal = toVal[:0]

	// Key 不存在或已经过期
	if err == storage.ErrKeyNotExists {
		return toVal, err
	}

	// Key 存在, 直接解码失败, 尝试类型转换
	anyVal, err := GetDefault().Get(key)
	if anyVal == nil || err != nil {
		if err != nil {
			return toVal, err
		}
		return toVal, errValueIsNotSlice
	}
	switch anyVal.(type) {
	case []any, []string, []bool,
		[]int, []int8, []int16, []int32, []int64,
		[]uint, []uint8, []uint16, []uint32, []uint64,
		[]float32, []float64,
		[]time.Time, []time.Duration, []time.Month, []time.Weekday:
		return values.ToSliceAsE[T](anyVal)
	case [][]any, [][]string, [][]bool,
		[][]int, [][]int8, [][]int16, [][]int32, [][]int64,
		[][]uint, [][]uint8, [][]uint16, [][]uint32, [][]uint64,
		[][]float32, [][]float64,
		[][]time.Time, [][]time.Duration, [][]time.Month, [][]time.Weekday:
		return values.ToSliceAsE[T](anyVal)
	default:
		return toVal, errValueIsNotSlice
	}
}

// GetSliceMap 获取 []map[K]V 类型的缓存值, 如果不存在或已经过期则返回空值
//   - 支持转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceMap[K, V values.TypeBase](key string) []map[K]V {
	val, _ := GetSliceMapE[K, V](key)
	return val
}

// GetSliceMapD 获取 []map[K]V 类型的缓存值, 如果不存在或已经过期则返回默认值
//   - 支持转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceMapD[K, V values.TypeBase](key string, defaultVal []map[K]V) []map[K]V {
	if key == "" {
		return defaultVal
	}
	val, err := GetSliceMapE[K, V](key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetSliceMapE 获取 []map[K]V 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 支持转换目标为任意类型的 []map[K]V 切片, 如果转换失败, 则返回空的 []map[K]V 切片
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration | time.Month | time.Weekday
func GetSliceMapE[K, V values.TypeBase](key string) ([]map[K]V, error) {
	toVal := []map[K]V{}
	if key == "" {
		return toVal, storage.ErrKeyIsEmpty
	}
	err := GetDefault().Scan(key, &toVal)
	if err == nil {
		return toVal, nil
	}
	toVal = toVal[:0]
	// Key 不存在或已经过期
	if err == storage.ErrKeyNotExists {
		return toVal, err
	}
	// Key 存在, 直接解码失败, 尝试类型转换
	anyMap := []map[any]any{}
	err = GetDefault().Scan(key, &anyMap)
	if err == nil {
		return values.ToSliceMapE[K, V](anyMap)
	}
	return toVal, errValueIsNotSlice
}
